package ch.ffhs.bscinf2009.organizeanything.gui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.Toast;
import ch.ffhs.bscinf2009.organizeanything.Environment;
import ch.ffhs.bscinf2009.organizeanything.R;
import ch.ffhs.bscinf2009.organizeanything.data.AbstractType;
import ch.ffhs.bscinf2009.organizeanything.data.DateType;
import ch.ffhs.bscinf2009.organizeanything.data.Organizable;
import ch.ffhs.bscinf2009.organizeanything.data.StringType;
import ch.ffhs.bscinf2009.organizeanything.data.ValueChooserType;

/**
 * @author lir
 * Populates a screen where the user can define a new definition
 */
public class CreateNewObjectType extends Activity {
	private TableLayout tb;
	private Organizable definition;
	private final int SUB_ACTIVITY_REQUEST_CODE = 99;
	private final String CHOOSER = "Chooser";
	private final String STRING = "Text";
	private final String DATEPICKER = "Date";
	private Map<Integer, String> map = new HashMap<Integer, String>();
	private EditText title;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.organizable_create_definition);
		tb = (TableLayout) findViewById(R.id.table_manage_object);
		title = (EditText) findViewById(R.id.manage_object_name);
		title.requestFocus();
		addProperty(null);
	}

	/**
	 * adds a new property line
	 * @param view the view the method was called from
	 */
	public void addProperty(View view) {
		TableRow tr = new TableRow(getBaseContext());
		final EditText etProperty = new EditText(this);
		etProperty.setText("");
		if (view != null) {
			etProperty.requestFocus();
		}

		final Spinner spin = new Spinner(this);
		String[] possibleData = new String[] { STRING, CHOOSER, DATEPICKER };
		ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_item, possibleData);
		dataAdapter
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		spin.setAdapter(dataAdapter);
		spin.setId(tb.getChildCount() + 1);
		spin.setSelection(0);
		spin.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				if (CHOOSER.equals(spin.getSelectedItem().toString())) {
					Intent intent = new Intent(CreateNewObjectType.this,
							CreateDefinitionChooser.class);
					intent.putExtra("spinnerID", spin.getId());
					intent.putExtra("propertyName", etProperty.getText()
							.toString());
					startActivityForResult(intent, SUB_ACTIVITY_REQUEST_CODE);
				} else {
					if (map.containsKey(spin.getId())) {
						map.remove(spin.getId());
					}
				}
			}

			public void onNothingSelected(AdapterView<?> arg0) {
			}

		});

		EditText etDatatype = new EditText(this);
		etDatatype.setText("Datatype");
		tr.addView(etProperty);
		tr.addView(spin);
		tb.addView(tr);
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == SUB_ACTIVITY_REQUEST_CODE) {
			Bundle bundle = data.getExtras();
			map.put(bundle.getInt("spinnerID"), bundle.getString("VALUES"));
		}
	}

	/**
	 * removes the last property line
	 * @param view the view the method was called from
	 */
	public void removeProperty(View view) {
		int i = tb.getChildCount();
		if (i > 2) {
			TableRow tr = (TableRow) tb.getChildAt(i - 1);
			tb.removeView(tr);
		}
	}

	/**
	 * Stores the created definition in the database
	 * @param view the view the method was called from
	 */
	public void createDefinition(View view) {
		
		String titleString = title.getText().toString();
		Pattern p = Pattern.compile("[a-zA-Z_0-9]+");
		Matcher matcher = p.matcher(titleString);
		if (!matcher.matches()){
			CharSequence text = "Title can contain characters and numbers only and must have one character at least";
			int duration = Toast.LENGTH_LONG;
			Toast.makeText(this, text, duration).show();
			return;
		} 
		
		// Create new Organizable
		definition = new Organizable();
		// Tell the name of new Organizable
		definition.setOrganizableName(title.getText().toString());
		// Create List for properties
		List<AbstractType> properties = new ArrayList<AbstractType>();

		// i starts at 1, because 0 is the table header which is not needed data
		for (int i = 1; i < tb.getChildCount(); i++) {
			TableRow tr = (TableRow) tb.getChildAt(i);
			EditText etProperty = (EditText) tr.getChildAt(0);
			Spinner spin = (Spinner) tr.getChildAt(1);

			String propName = etProperty.getText().toString();
			matcher = p.matcher(propName);
			if (!matcher.matches()){
				CharSequence text = "Properties can contain characters and numbers only and must have one character at least";
				int duration = Toast.LENGTH_LONG;
				Toast.makeText(this, text, duration).show();
				return;
			} 
			if (CHOOSER.equals(spin.getSelectedItem())) {
				// Create Object for ValueChooser
				ValueChooserType valueChooser = new ValueChooserType();
				valueChooser.setPropertyName(propName);
				valueChooser.setDescriptorValue(i == 1);
				valueChooser.parseTypeDefinition(map.get(spin.getId()));
				properties.add(valueChooser);

			} else if (DATEPICKER.equals(spin.getSelectedItem())) {
				DateType dt = new DateType();
				dt.setDescriptorValue(i == 1);
				dt.setPropertyName(propName);
				properties.add(dt);
			} else {
				// Create Object for StringType
				StringType stringType = new StringType();
				stringType.setPropertyName(propName);
				stringType.setDescriptorValue(i == 1);
				properties.add(stringType);
			}
		}

		// Save properties to Organizable object
		definition.setProperties(properties);
		// Create the definition in DB
		Environment.getInstance().getDB(this).saveDefintion(definition);
		// Go back to start screen
		final Intent i = new Intent(CreateNewObjectType.this,
				OrganizableTypeList.class);
		startActivity(i);
	}
}
